﻿using System;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Ecobee.Net
{
	/// <summary>
	/// 
	/// </summary>
	public class Authorization : ApiObject
	{
		private string _ecobeePin = string.Empty;
		private TimeSpan _expiresIn = TimeSpan.Zero;
		private AuthorizationScope _responseScope = AuthorizationScope.None;
		private Token _authorizationToken = new Token(Token.Kind.Authorization);
		private TimeSpan _interval = TimeSpan.Zero;
		private DateTime _timeStamp = DateTime.MinValue;

		/// <summary>
		/// 
		/// </summary>
		/// <param name="responseScope"></param>
		public Authorization(AuthorizationScope responseScope)
		{
			this.ResponseScope = responseScope;
		}

		/// <summary>
		/// The PIN a user enters in the web portal.
		/// </summary>
		public string EcobeePin
		{
			get
			{
				return _ecobeePin;
			}
			internal set
			{
				_ecobeePin = value;
			}
		}

		/// <summary>
		/// The amount of time until the PIN expires. Ensure you inform the user how much time they have.
		/// </summary>
		public TimeSpan Lifetime
		{
			get
			{
				return _expiresIn;
			}
			internal set
			{
				_expiresIn = value;
			}
		}

		/// <summary>
		/// The amount of time until this authorization expires.
		/// </summary>
		public TimeSpan ExpiresIn
		{
			get
			{
				return DateTime.Now.Subtract(this.ExpiresAt);
			}
		}

		/// <summary>
		/// The authorization token needed to request the access and refresh tokens.
		/// </summary>
		public AuthorizationScope ResponseScope
		{
			get
			{
				return _responseScope;
			}
			internal set
			{
				_responseScope = value;
			}
		}

		/// <summary>
		/// The requested Scope from the original request. This must match the original request.
		/// </summary>
		public Token AuthorizationToken
		{
			get
			{
				return _authorizationToken;
			}
			internal set
			{
				_authorizationToken = value;
			}
		}

		/// <summary>
		/// The minimum amount of seconds which must pass between polling attempts for a token.
		/// </summary>
		public TimeSpan Interval
		{
			get
			{
				return _interval;
			}
			internal set
			{
				_interval = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public DateTime TimeStamp
		{
			get
			{
				return _timeStamp;
			}
			internal set
			{
				_timeStamp = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public DateTime ExpiresAt
		{
			get
			{
				return this.TimeStamp.Add(this.Lifetime);
			}
		}

		/// <summary>
		/// Makes a request for the a new Authorization with the specified scope.
		/// </summary>
		/// <returns></returns>
		public async Task<bool> GetPinAuthorization()
		{
			bool returnValue = false;

			ApiResult response = await Api.Http.Get(Api.KnownUri.GetPinAuthorization(this.ResponseScope));

			if (response.Successful)
			{
				this.FromDataObject(response.DataObject);
				returnValue = true;
			}

			return returnValue;
		}

		protected override void OnFromDataObject(dynamic dataObject)
		{
			string scopeValue = Convert.ToString(dataObject.scope);
			this.EcobeePin = dataObject.ecobeePin;
			this.AuthorizationToken = new Token() { TokenKind = Token.Kind.Authorization, Identifier = dataObject.code };
			this.Lifetime = TimeSpan.FromMinutes(((JValue)dataObject.expires_in).ToObject<int>());
			this.Interval = TimeSpan.FromSeconds(((JValue)dataObject.interval).ToObject<int>());
			this.ResponseScope = scopeValue.FromApiString();
			this.TimeStamp = DateTime.Now;
		}
	}
}
